package essential;

import primitives.*;
import shaders.Shader;

import java.util.ArrayList;
import java.util.HashMap;

import javax.vecmath.Vector3d;

import CGParser.SCParser;

public class Scene {
	protected KDTreeNode spacePartition;
	
	public int width;
	public int height;
	
	public int aaMin;
	public int aaMax;
	public Camera camera;
	
	public int threadsCount;
	
    public HashMap<String, Shader> shadersMap;
    public HashMap<String, Renderable> geometriesMap;
	public ArrayList<Renderable> lightRenderables;
	public ArrayList<Renderable> renderables;

	public Scene copy() {
		Scene s = new Scene();
		s.width = width;
		s.height = height;
		s.aaMax = aaMax;
		s.camera = camera.copy();
		
		s.lightRenderables = new ArrayList<Renderable>();
		for (int i=0; i<lightRenderables.size(); i++)
			s.lightRenderables.add(lightRenderables.get(i).copy());

		s.renderables = new ArrayList<Renderable>();
		for (int i=0; i<renderables.size(); i++)
			s.renderables.add(renderables.get(i).copy());
		
		s.calculateSpacePartition();
		return s;
	}
	
	public Scene(){
		shadersMap = new HashMap<String,Shader>();
		geometriesMap = new HashMap<String, Renderable>();
		lightRenderables= new ArrayList<Renderable>();
		renderables = new ArrayList<Renderable>();
		width = 0;
		height = 0;
		threadsCount = 0;
		camera = null;
	}
   
	public static Scene LoadScene(String fileName) {
		
		Scene scene = new Scene();
		SCParser p = new SCParser(); 
		
		if(p.parse(fileName,scene) == false){
			System.out.printf("Error: The parser was unable to parse the file %s\n",fileName);
			return null;
		}
		
		
		scene.calculateSpacePartition();
		
		return scene;
	
	}
	
	public void calculateSpacePartition(){
		
	/*	for(int i = 0; i < 4; i++){
    		for(int j = 0; j < 4; j++){
    			for(int w = 0; w < 4; w++){
    				double leftOffset = 2.25;
    				double offset = 1.5;
    				double x = -leftOffset+ i*offset;
    				double y = -leftOffset+ j*offset;
    				double z = -leftOffset+ w*offset;
    			
    				System.out.println("object {\n shader randomShader\n type sphere\n name sphere"+i+j+w+"\n c "+x+' '+y+' '+z+"\n r 0.5\n}");
    			
       			}
    		}
    	}
			*/
		
		AxisAlignedBoundingBox aabb = new AxisAlignedBoundingBox();
	
		for (int i = 0; i < renderables.size(); i++) {
			aabb.sum(renderables.get(i).getAABB());
		}
		
		this.spacePartition = KDTree.BuildKDTree(renderables, aabb, 20);
	}
	
	
	public int getRenderableCount() {
		return renderables.size();
	}

    public Renderable getRenderable(int index){
    	return this.renderables.get(index);
    }
    
    public Renderable intersect(Ray r) {
    	return spacePartition.intersect(r);
    }
    
    
    
    public ArrayList<Renderable>  getPrimitives(){
    	return renderables;
    }
}
